package com.tencent.sr.iris.activity.service.event.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.tencent.sr.iris.activity.common.enums.TaskBatchDateIsParticipatedEnum;
import com.tencent.sr.iris.activity.common.enums.UserTaskRecordStatusEnum;
import com.tencent.sr.iris.activity.common.enums.UserTaskStatusEnum;
import com.tencent.sr.iris.activity.common.util.ShardingIdUtil;
import com.tencent.sr.iris.activity.domain.event.dto.ActivityTaskDTO;
import com.tencent.sr.iris.activity.domain.event.dto.InviteLimitDTO;
import com.tencent.sr.iris.activity.interfaces.enums.ActivityTypeEnum;
import com.tencent.sr.iris.activity.interfaces.event.dto.ActivityEventDTO;
import com.tencent.sr.iris.activity.repository.entity.TIrisUserTaskRecordDO;
import com.tencent.sr.iris.activity.repository.mapper.TIrisUserTaskRecordMapper;
import com.tencent.sr.iris.activity.repository.mapper.example.TIrisUserTaskRecordExample;
import com.tencent.sr.iris.activity.service.activity.ActivityCommonService;
import com.tencent.sr.iris.activity.service.activity.IrisUserTaskRecordService;
import com.tencent.sr.iris.activity.service.constant.ActivityRedisKey;
import com.tencent.sr.rmall.common.exception.retail.TRetailErrorException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 上级变更事件处理器
 *
 * 注：事件处理器的spring对象名使用对应事件枚举的code
 * com.tencent.sr.iris.activity.interfaces.enums.ActivityEventTypeEnum
 *
 * @author xiaojun
 */
@Slf4j
@Component("SUPERVISOR_CHANGE")
public class IrisSupervisorChangeEventHandler extends AbstractIrisEventHandler {

    @Resource
    private TIrisUserTaskRecordMapper irisUserTaskRecordMapper;

    @Resource
    private ActivityCommonService activityCommonService;

    @Resource
    private IrisUserTaskRecordService userTaskRecordService;

    @Resource
    private RedissonClient redissonClient;

    /**
     * 分布式锁最大执行时间30秒
     */
    private static final int MAX_LOCK_TIME = 30;

    @Override
    void process(ActivityEventDTO eventDTO, List<String> eventHandingInfoList) {
        //查询该用户的所有未发奖的任务进度记录,且记录为非失效状态
        log.info("query userTaskRecord");
        List<TIrisUserTaskRecordDO> userTaskRecordDOList = queryUserTaskRecordList(eventDTO.getUid());
        //更新任务进度记录上级
        log.info("update userTaskRecord pid");
        userTaskRecordDOList.forEach(r -> {
            if (StringUtils.isNotBlank(eventDTO.getPid()) && !eventDTO.getPid().equals(r.getPid())) {
                InviteLimitDTO result = queryInviteLimit(r, eventDTO, eventHandingInfoList);
                updateTaskRecordPid(r, eventDTO.getPid(), result);
            } else {
                StringBuilder str = new StringBuilder().append("用户上级没变,不处理")
                        .append(",uid:").append(r.getUid()).append(",oldPid=").append(r.getPid())
                        .append(",newPid=").append(eventDTO.getPid());
                eventHandingInfoList.add(str.toString());
                log.info("用户上级没变,不处理，uid={},oldPid={},newPid={},oldRecord:{},eventDTO:{}",
                        r.getUid(), r.getPid(), eventDTO.getPid(), JSON.toJSONString(r), JSON.toJSONString(eventDTO));
            }
        });
    }

    @SneakyThrows
    private InviteLimitDTO queryInviteLimit(TIrisUserTaskRecordDO r, ActivityEventDTO eventDTO,
            List<String> eventHandingInfoList) {
        InviteLimitDTO result = null;
        String uid = eventDTO.getUid();
        //邀请有礼活动判断是否限额,6月22日 0点后成为见习会员的团长发生的转移做此处理
        if (r.getActivityId().equals(ActivityTypeEnum.INVITE_GIFT.getCode())) {
            //查询成为见习时间
            Long becomeTraineeTime = activityCommonService.queryTraineeTime(uid);
            log.info("上级变更，所变更团长信息，uid:{},becomeTraineeTime:{}", uid, becomeTraineeTime);
            if (becomeTraineeTime >= activityCommonService.queryInviteChangeTime(uid)) {
                RLock lock = null;
                try {
                    String lockKey = ActivityRedisKey.getInviteTaskLockKey(eventDTO.getPid());
                    lock = redissonClient.getLock(lockKey);
                    if (!lock.tryLock(MAX_LOCK_TIME, TimeUnit.SECONDS)) {
                        eventHandingInfoList.add("任务处理：获取分布式锁失败，当前上级邀请任务正在处理");
                        log.info("任务处理：获取分布式锁失败，当前上级邀请任务正在处理,pid:{},uid:{},msgId:{}",
                                eventDTO.getPid(), eventDTO.getUid(), eventDTO.getIdempotent());
                        return null;
                    }
                    //查询是否还有邀请名额, 0701前成为见习的按照邀请获取上限,0701后的按照派奖获取上限
                    if (becomeTraineeTime <  activityCommonService.queryInviteUpperLimitChangeTime(uid)){
                        result = activityCommonService.queryInviteLimit(eventDTO.getPid(), becomeTraineeTime);
                    } else {
                        result = activityCommonService.queryInviteLimitByAward(eventDTO.getPid(), becomeTraineeTime);
                    }
                    if (result.isError()) {
                        log.error("查询邀请上限失败，pid：{}，inviteLimitDTO：{}", eventDTO.getPid(), JSON.toJSONString(result));
                        throw new TRetailErrorException(result.getDesc() + "，查询邀请上限失败");
                    }
                    if (!result.isSatisfy()) {
                        log.info("不满足邀请上限规则,uid={},pid={},errorMsg:{}, msg={},inviteLimitDTO={}", eventDTO.getUid(),
                                eventDTO.getPid(), result.getDesc(),
                                JSONObject.toJSONString(eventDTO), JSONObject.toJSONString(result));
                        eventHandingInfoList.add("不满足邀请上限规则,msg=" + result.getDesc());
                    }
                } finally {
                    if (lock != null) {
                        lock.unlock();
                    }
                }
            }
        }
        return result;
    }


    @Transactional(rollbackFor = Exception.class)
    protected void updateTaskRecordPid(TIrisUserTaskRecordDO r, String newPid, InviteLimitDTO inviteLimit) {
        log.info("用户上级变更,oldRecord:{}", JSON.toJSONString(r));
        //更新原任务进度为新上级
        TIrisUserTaskRecordExample updateExample = new TIrisUserTaskRecordExample();
        updateExample.createCriteria().andPropertyEqualTo(TIrisUserTaskRecordExample.ID, r.getId())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.USER_TASK_STATUS,
                        UserTaskStatusEnum.PROGRESS.getCode())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.SHARDING_ID, r.getShardingId());
        TIrisUserTaskRecordDO newPidUpdate = new TIrisUserTaskRecordDO();
        newPidUpdate.setPid(newPid);
        if (Objects.nonNull(inviteLimit)) {
            //查询成为见习时间
            Long becomeTraineeTime = activityCommonService.queryTraineeTime(r.getUid());
            if (becomeTraineeTime <  activityCommonService.queryInviteUpperLimitChangeTime(r.getUid())) {
                //如果超过新上级上限的话，状态置为已超限状态
                if (BooleanUtils.isFalse(inviteLimit.isSatisfy())) {
                    newPidUpdate.setIsParticipated(TaskBatchDateIsParticipatedEnum.LIMITED.getCode());
                    newPidUpdate.setUserTaskStatus(UserTaskStatusEnum.LIMITED.getCode());
                    newPidUpdate.setEstimateUserTaskStatus(UserTaskStatusEnum.LIMITED.getCode());
                }
                //记录成为见习当月邀请上限和邀请次序
                newPidUpdate.setInviteLimit(inviteLimit.getInviteLimit());
                newPidUpdate.setInviteSeq(inviteLimit.getInviteSeq());
            } else {
                if (BooleanUtils.isFalse(inviteLimit.isSatisfy())) {
                    newPidUpdate.setIsParticipated(TaskBatchDateIsParticipatedEnum.LIMITED.getCode());
                }
                newPidUpdate.setInviteLimit(inviteLimit.getInviteLimit());
            }

        }
        log.info("用户上级变更,uid={},oldPid={},newPid={},inviteLimit:{}", r.getUid(), r.getPid(), newPid,
                JSON.toJSONString(inviteLimit));
        int res = irisUserTaskRecordMapper.updateByExampleSelective(newPidUpdate, updateExample);
        //清除新/老上级上限名额缓存
        userTaskRecordService.deleteInviteLimitCache(r.getPid(), r.getUid());
        userTaskRecordService.deleteInviteLimitCache(newPid, r.getUid());
        log.info("用户上级变更结果={}", res > 0);
    }

    private List<TIrisUserTaskRecordDO> queryUserTaskRecordList(String uid) {
        TIrisUserTaskRecordExample example = new TIrisUserTaskRecordExample();
        example.createCriteria().andPropertyEqualTo(TIrisUserTaskRecordExample.UID, uid)
                .andPropertyIn(TIrisUserTaskRecordExample.USER_TASK_STATUS,
                        Lists.newArrayList(UserTaskStatusEnum.PROGRESS.getCode(), UserTaskStatusEnum.LIMITED.getCode()))
                .andPropertyEqualTo(TIrisUserTaskRecordExample.STATUS, UserTaskRecordStatusEnum.NORMAL.getCode())
                .andPropertyEqualTo(TIrisUserTaskRecordExample.SHARDING_ID, ShardingIdUtil.sharding(uid));
        return irisUserTaskRecordMapper.selectByExample(example);
    }

    @Override
    public void after(ActivityEventDTO eventDTO) {

    }


    @Override
    List<ActivityTaskDTO> getRelatedTaskList(String eventType) {
        return null;
    }

    @Override
    void baseDataProcess(ActivityEventDTO eventDTO) {

    }
}
